import React, { createContext, useContext, useState, ReactNode, useCallback } from 'react';
import { App, message } from 'antd';
import Loading from './Loading';

interface LoadingState {
  isLoading: boolean;
  loadingText?: string;
  overlay?: boolean;
}

interface LoadingContextType {
  loadingState: LoadingState;
  showLoading: (text?: string, overlay?: boolean) => void;
  hideLoading: () => void;
  withLoading: <T>(promise: Promise<T>, loadingText?: string) => Promise<T>;
}

const LoadingContext = createContext<LoadingContextType | undefined>(undefined);

export const useLoading = () => {
  const context = useContext(LoadingContext);
  if (!context) {
    throw new Error('useLoading must be used within a LoadingProvider');
  }
  return context;
};

interface LoadingProviderProps {
  children: ReactNode;
}

export const LoadingProvider: React.FC<LoadingProviderProps> = ({ children }) => {
  const [loadingState, setLoadingState] = useState<LoadingState>({
    isLoading: false,
    loadingText: undefined,
    overlay: false
  });
  const { message } = App.useApp();

  const showLoading = useCallback((text?: string, overlay = false) => {
    setLoadingState({
      isLoading: true,
      loadingText: text,
      overlay
    });
  }, []);

  const hideLoading = useCallback(() => {
    setLoadingState({
      isLoading: false,
      loadingText: undefined,
      overlay: false
    });
  }, []);

  const withLoading = useCallback(async <T,>(promise: Promise<T>, loadingText?: string): Promise<T> => {
    try {
      showLoading(loadingText, true);
      const result = await promise;
      hideLoading();
      return result;
    } catch (error) {
      hideLoading();
      throw error;
    }
  }, [showLoading, hideLoading]);

  const contextValue: LoadingContextType = {
    loadingState,
    showLoading,
    hideLoading,
    withLoading
  };

  return (
    <LoadingContext.Provider value={contextValue}>
      {children}
      {loadingState.isLoading && (
        <Loading
          spinning={true}
          text={loadingState.loadingText}
          overlay={loadingState.overlay}
          size="large"
        />
      )}
    </LoadingContext.Provider>
  );
};

// 便捷的 Hook 用于处理异步操作
export const useAsyncOperation = () => {
  const { withLoading } = useLoading();

  const executeWithFeedback = async <T,>(
    operation: () => Promise<T>,
    options?: {
      loadingText?: string;
      successMessage?: string;
      errorMessage?: string;
      onSuccess?: (result: T) => void;
      onError?: (error: any) => void;
    }
  ): Promise<T | undefined> => {
    try {
      const result = await withLoading(
        operation(),
        options?.loadingText || '处理中...'
      );
      
      if (options?.successMessage) {
        message.success(options.successMessage);
      }
      
      if (options?.onSuccess) {
        options.onSuccess(result);
      }
      
      return result;
    } catch (error: any) {
      const errorMessage = options?.errorMessage || 
        error?.message || 
        '操作失败，请重试';
      
      message.error(errorMessage);
      
      if (options?.onError) {
        options.onError(error);
      }
      
      return undefined;
    }
  };

  return { executeWithFeedback };
};

export default LoadingProvider;